
package com.AI;


import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;

import com.AI.R;
import com.google.android.maps.GeoPoint;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.hardware.Camera;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.LocationManager;
import android.net.Uri;
import android.opengl.GLU;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.provider.MediaStore.Images.Media;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.TextView;

public class CameraActivity extends Activity implements SurfaceHolder.Callback, SensorEventListener {

	private static final int TAKE_PHOTO_CODE = 1;
	private SurfaceView mSurfaceView;
	private SurfaceHolder mSurfaceHolder;
	private Camera mCamera;
	private boolean mPreviewRunning;
	private SensorManager mySensorManager;
	private SensorEventListener mySensorEventListener;
	private List<Sensor> mySensors;
	private CameraOverlayLayout cameraLayout;
	
	private int sensorOrientationIndex = 0;
	private int sensorAcceleroIndex = 0;
	private int sensorMagneticIndex = 0;
	
	public static Display display;
	
	float[] magneticValues;
	float[] accelerometerValues;
	
	TextView tv;
	
	public void onCreate(Bundle savedInstanceState)
	{
		
		super.onCreate(savedInstanceState );
		setContentView(R.layout.cameralayout);
		
		cameraLayout = (CameraOverlayLayout)findViewById(R.id.cameraOverlayLayout);
		cameraLayout.init();
		
		mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);
		mSurfaceHolder = mSurfaceView.getHolder();
		mSurfaceHolder.addCallback(this);
		mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		
		mySensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
		mySensors = mySensorManager.getSensorList(Sensor.TYPE_ALL);
		for (int i = 0; i<mySensors.size(); i++)
		{
			if (mySensors.get(i).getType() == Sensor.TYPE_ACCELEROMETER)
				sensorAcceleroIndex = i;
			if (mySensors.get(i).getType() == Sensor.TYPE_ORIENTATION)
				sensorAcceleroIndex = i;
			if (mySensors.get(i).getType() == Sensor.TYPE_MAGNETIC_FIELD)
				sensorMagneticIndex = i;
							
		}
		
		display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
		tv = (TextView) findViewById(R.id.sensors);
	}
	
	@Override
	protected void onResume()
	{
		super.onResume();
		Log.d("ADDING SENSORS:", sensorAcceleroIndex + " AND " + sensorOrientationIndex);
		mySensorManager.registerListener(this, mySensors.get(sensorAcceleroIndex), SensorManager.SENSOR_DELAY_GAME);
		mySensorManager.registerListener(this, mySensors.get(sensorOrientationIndex), SensorManager.SENSOR_DELAY_GAME);
		mySensorManager.registerListener(this, mySensors.get(sensorMagneticIndex), SensorManager.SENSOR_DELAY_GAME);

		
	}
	
	@Override
	protected void onStop()
	{
		super.onStop();
		mySensorManager.unregisterListener(this, mySensors.get(sensorAcceleroIndex));
		mySensorManager.unregisterListener(this, mySensors.get(sensorOrientationIndex));
		mySensorManager.unregisterListener(this, mySensors.get(sensorMagneticIndex));		

	}
	
	
	@Override
	protected void onDestroy()
	{
		super.onDestroy();
		mySensorManager.unregisterListener(this, mySensors.get(sensorAcceleroIndex));
		mySensorManager.unregisterListener(this, mySensors.get(sensorOrientationIndex));
		mySensorManager.unregisterListener(this, mySensors.get(sensorMagneticIndex));

	}

	//@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		if (mPreviewRunning)
			mCamera.stopPreview();
		
		Camera.Parameters p = mCamera.getParameters();
		
		p.setPreviewSize(800, 480);
		mCamera.setParameters(p);
		try{
			mCamera.setPreviewDisplay(holder);
		} catch(IOException e){
			e.printStackTrace();
		}
		mCamera.startPreview();
		mPreviewRunning = true;
		
		cameraLayout.invalidate();
	}
	
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data)
	{
		if (resultCode == RESULT_OK)
		{
			switch(requestCode){
			case TAKE_PHOTO_CODE:
			}
		}
	}

	//@Override
	public void surfaceCreated(SurfaceHolder holder) {
		mCamera = Camera.open();
	}

	//@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		mCamera.stopPreview();
		mPreviewRunning = false;
		mCamera.release();
	}
	
	//@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
	}

	//@Override
	public void onSensorChanged(SensorEvent event) {
		synchronized (this) {
            if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
            	UserModel.azimuth = event.values[0];
            	UserModel.pitch = event.values[1];            
            	UserModel.roll = event.values[2];
            	
            }
            if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
            	UserModel.x_acc = event.values[0];
            	UserModel.y_acc = event.values[1];
            	UserModel.z_acc = event.values[2];
            	accelerometerValues = event.values.clone();
            }
            if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
            	magneticValues = event.values.clone();
            }
//            ((TextView) findViewById(R.id.sensors)).setText("X Direction: " + UserModel.pitch + 
//    	    						"\nY Direction: " + UserModel.roll + "\nZ Direction: " + UserModel.azimuth + 
 //   	    						"\nX Acc: " + UserModel.x_acc + "\nY Acc: " + UserModel.y_acc + "\nZ Acc: " + UserModel.z_acc + "\nXcoord: " + UserModel.Xcoord);

            if (magneticValues != null && accelerometerValues != null)
            {
	            float[] R = new float[16];
	            float[] I = new float[16];
	            
	            SensorManager.getRotationMatrix(R, I, accelerometerValues, magneticValues);
	            float[] orientation = new float[3];
	            SensorManager.getOrientation(R, orientation);
	            
	            UserModel.azimuth = Math.toDegrees(orientation[0]);
	            UserModel.pitch = Math.toDegrees(orientation[1]);
	            UserModel.roll = Math.toDegrees(orientation[2]);
	            
	            tv.setText("Azimuth: " + (int)UserModel.azimuth + 
						"\nPitch: " + (int)UserModel.pitch + "\nRoll: " + (int)UserModel.roll + 
						"\nX Acc: " + UserModel.x_acc + "\nY Acc: " + UserModel.y_acc + "\nZ Acc: " + UserModel.z_acc);
	            
	            
	            //gl.glRotatef(orientation[2],0,1,0);

            }

            if (CameraOverlayLayout.tracking)
            	updateTracking();
            
            
		}
	}
	
	public void updateTracking()
	{
		// update usermodel etc. here
		
		// camera projection
		double pi180 = Math.PI / 180;
		
		//UserModel.pitch = -UserModel.pitch + UserModel.lati - 90;
		//UserModel.roll = UserModel.roll*Math.sin(UserModel.lati*(pi180)) - 
		//	UserModel.azimuth * Math.cos(UserModel.lati*pi180);
		//UserModel.azimuth = -UserModel.roll * Math.cos(UserModel.lati * pi180) -
		//	UserModel.azimuth * Math.sin(UserModel.lati * pi180) + UserModel.longi - 90;
		
		
		double cosOx = Math.cos(-UserModel.pitch*pi180); // werkt
		double sinOx = Math.sin(-UserModel.pitch*pi180);
		double cosOy = Math.cos(UserModel.roll*pi180); // vreemd
		double sinOy = Math.sin(UserModel.roll*pi180);
		double cosOz = Math.cos(UserModel.azimuth*pi180);  // werkt
		double sinOz = Math.sin(UserModel.azimuth*pi180);
		
		double ax = UserModel.point_x;
		double ay = UserModel.point_y;
		double az = UserModel.point_z;
		
		double cx = 0;
		double cy = 0;
		double cz = 0;
		//double cx = UserModel.camera_x;
		//double cy = UserModel.camera_y;
		//double cz = UserModel.camera_z;
		
		double dx = cosOy * (sinOz * (ay-cy) + cosOz * (ax-cx)) - sinOy *(az-cz);
		double dy = sinOx * (cosOy * (az-cz) + sinOy * (sinOz * (ay-cy) + cosOz *
		(ax-cx))) + cosOx * (cosOz * (ay-cy) - sinOz * (ax-cx));
		double dz = cosOx * (cosOy * (az-cz) + sinOy * (sinOz * (ay-cy) + cosOz *
		(ax-cx))) - sinOx * (cosOz * (ay-cy) - sinOz * (ax-cx));
					
		double bx = dx/dz;
		double by = dy/dz;
		
		// scale projection coordinates to telephone screen
		UserModel.Ycoord = 240*bx;
		UserModel.Xcoord = 400*by;
	}
	
	public int angleToPixel(double angle){
		int pixel = (int) (angle/45.0 * 800);
		return pixel;
	}
	
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event)
	{
		if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER){
			cameraLayout.toggleTracking();
			return true;
		}
		return false;
	}
}
